#include "HiVideoVproc.h"

#include <string>
#include <stdio.h>


#include "hi_mapi_venc.h"
#include "hi_mapi_vproc.h"
#include "hi_mapi_sys.h"
#include "hi_mapi_vgs.h"
#include "HiMediaSystem.h"
#include "hi_comm_vgs.h"


HiVideoVproc::HiVideoVproc()
{
    m_width = 1920;
    m_height = 1080;
    m_image = NULL;
}


HiVideoVproc::HiVideoVproc(HI_S32 width, HI_S32 height)
{
    m_width = width;
    m_height = height;
    m_image = NULL;
}

HiVideoVproc::~HiVideoVproc()
{
   if(m_image != NULL)
    {
       free(m_image);
       m_image = NULL;
    }
}

HI_S32 HiVideoVproc::GetFrame(HI_HANDLE grpHdl, HI_HANDLE portHdl, HiImage& image)
{
    HI_MAPI_FRAME_DATA_S frameData;
    memset(&frameData, 0, sizeof(HI_MAPI_FRAME_DATA_S));
    HI_S32 ret = HI_MAPI_VPROC_GetPortFrame(grpHdl, portHdl, HI_FALSE, &frameData);
    if(ret != HI_SUCCESS) {
        printf("HI_MAPI_VPROC_GetPortFrame failed ret:0x%x, mVpssHdl:%d, mVpssPort:%d\n", ret, grpHdl, portHdl);
        return ret;
    }
    image.phyAddr = frameData.u64PhyAddr[0];
    image.virAddr = frameData.u64VirAddr[0];
    image.stride = frameData.u32Stride[0];
    image.width = frameData.u32Width;
    image.height = frameData.u32Height;
    image.imgPts = (HI_U32)frameData.u64pts;
    if (m_image == NULL)
    {
        m_image = (HI_VOID*) malloc(sizeof(HI_MAPI_FRAME_DATA_S));
    }

    memcpy(m_image, &frameData, sizeof(HI_MAPI_FRAME_DATA_S));
    return HI_SUCCESS;

}

HI_S32 HiVideoVproc::ReleaseFrame(HI_HANDLE grpHdl, HI_HANDLE portHdl, HiImage& image)
{
    HI_S32 ret = HI_SUCCESS;
    if (m_image != NULL) {
        ret = HI_MAPI_VPROC_ReleasePortFrame(grpHdl, portHdl, HI_FALSE, (HI_MAPI_FRAME_DATA_S*)m_image);
        if(ret != HI_SUCCESS) {
            printf("Error, HI_MAPI_VPROC_ReleasePortFrame ret:0x%x\n", ret);
            return HI_FAILURE;
        }
        printf("realeas port frame:%p \n", m_image);
    }

    return HI_SUCCESS;
}

HI_S32 HiVideoVproc::StartPort(HI_HANDLE vpssHdl, HI_HANDLE portHdl)
{
    HI_S32 ret = HI_SUCCESS;

    HI_MAPI_VPSS_ATTR_S vpssAttr;
    memset(&vpssAttr, 0x00, sizeof(vpssAttr));
    vpssAttr.u32MaxW = m_width;
    vpssAttr.u32MaxH = m_height;
    vpssAttr.stFrameRate.s32SrcFrameRate = 30;
    vpssAttr.stFrameRate.s32DstFrameRate = 30;
    vpssAttr.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    vpssAttr.bNrEn = HI_FALSE;
    vpssAttr.stNrAttr.enNrType = VPSS_NR_TYPE_VIDEO;
    vpssAttr.stNrAttr.enCompressMode = COMPRESS_MODE_NONE;
    vpssAttr.stNrAttr.enNrMotionMode = NR_MOTION_MODE_NORMAL;
    ret = HI_MAPI_VPROC_InitVpss(vpssHdl, &vpssAttr);
    if(ret != HI_SUCCESS) {
        printf("HI_MAPI_VPROC_InitVpss error\n");
        return HI_FAILURE;
    }

    HI_MAPI_VPORT_ATTR_S previewPortAttr;
    memset(&previewPortAttr, 0x00, sizeof(previewPortAttr));
    previewPortAttr.u32Width = m_width;
    previewPortAttr.u32Height = m_height;
    previewPortAttr.stFrameRate.s32SrcFrameRate = 30;
    previewPortAttr.stFrameRate.s32DstFrameRate = 30;
    previewPortAttr.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    previewPortAttr.enVideoFormat = VIDEO_FORMAT_LINEAR;
    previewPortAttr.enCompressMode = COMPRESS_MODE_NONE;
    previewPortAttr.stAspectRatio.enMode = ASPECT_RATIO_NONE;
    previewPortAttr.lowDelayInfo.enable = HI_FALSE;
    ret = HI_MAPI_VPROC_SetPortAttr(vpssHdl, portHdl, &previewPortAttr);
    if(ret != HI_SUCCESS) {
        printf("HI_MAPI_VPROC_SetPortAttr error\n");
        return HI_FAILURE;
    }
    ret = HI_MAPI_VPROC_StartPort(vpssHdl, portHdl);
    if(ret != HI_SUCCESS) {
        printf("HI_MAPI_VPROC_StartPort error\n");
        return HI_FAILURE;
    }

    return HI_SUCCESS;

}

HI_S32 HiVideoVproc::ResizeImg(HiImage& inImage, HiImage& outImage)
{
    HI_S32 ret = HI_SUCCESS;
    HI_HANDLE vgsHandle;

    ret = HI_MAPI_VGS_BeginJob(&vgsHandle);
    if (ret != HI_SUCCESS) {
        printf("error: HI_MAPI_VGS_BeginJob ret: %x\n", ret);
        return HI_FAILURE;
    }
    HI_MAPI_VGS_ScaleTaskAttr scaleTaskAttr;
    memset(&scaleTaskAttr, 0, sizeof(scaleTaskAttr));
    scaleTaskAttr.scaleCoefMode = HI_MAPI_VGS_SCLCOEF_NORMAL;
    HI_MAPI_FRAME_DATA_S vgsInImage;
    memset(&vgsInImage, 0, sizeof(vgsInImage));
    vgsInImage.enCompressMode = COMPRESS_MODE_NONE;
    vgsInImage.enFrameDataType = HI_FRAME_DATA_TYPE_YUV;
    vgsInImage.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    vgsInImage.u32Height = inImage.height;
    vgsInImage.u32Width = inImage.width;
    vgsInImage.u32Stride[0] = inImage.stride;
    vgsInImage.u32Stride[1] = inImage.stride;
    vgsInImage.u64VirAddr[0] = inImage.virAddr;
    vgsInImage.u64VirAddr[1] = inImage.virAddr + inImage.stride * inImage.height;
    vgsInImage.u64PhyAddr[0] = inImage.phyAddr;
    vgsInImage.u64PhyAddr[1] = inImage.phyAddr + inImage.stride * inImage.height;

    //printf("inImage_phyaddr=%llu\n", vgsInImage.u64PhyAddr[0]);
    memcpy(&scaleTaskAttr.vgsTaskAttr.frameDataIn, &vgsInImage, sizeof(vgsInImage));

    HI_MAPI_FRAME_DATA_S vgsOutImage;
    memset(&vgsOutImage, 0, sizeof(vgsOutImage));
    vgsOutImage.enCompressMode = COMPRESS_MODE_NONE;
    vgsOutImage.enFrameDataType = HI_FRAME_DATA_TYPE_YUV;
    vgsOutImage.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    vgsOutImage.u32Height = outImage.height;
    vgsOutImage.u32Width = outImage.width;
    vgsOutImage.u32Stride[0] = outImage.stride;
    vgsOutImage.u32Stride[1] = outImage.stride;
    vgsOutImage.u64VirAddr[0] = outImage.virAddr;
    vgsOutImage.u64VirAddr[1] = outImage.virAddr + outImage.stride * outImage.height;
    vgsOutImage.u64PhyAddr[0] = outImage.phyAddr;
    vgsOutImage.u64PhyAddr[1] = outImage.phyAddr + outImage.stride * outImage.height;
    memcpy(&scaleTaskAttr.vgsTaskAttr.frameDataOut, &vgsOutImage, sizeof(vgsOutImage));
    ret = HI_MAPI_VGS_AddScaleTask(vgsHandle, &scaleTaskAttr);
    if (ret != HI_SUCCESS) {
        printf("error: HI_MAPI_VGS_AddScaleTask ret: %x\n", ret);
        goto EndJob;
    }
    ret = HI_MAPI_VGS_EndJob(vgsHandle);
    if (ret != HI_SUCCESS) {
        printf("error: HI_MAPI_VGS_EndJob ret: %x\n", ret);
        return HI_FAILURE;
    }
    return HI_SUCCESS;
EndJob:
    HI_MAPI_VGS_EndJob(vgsHandle);
    return ret;

    return HI_SUCCESS;
}


HI_S32 HiVideoVproc::StopPort(HI_HANDLE vpssHdl, HI_HANDLE portHdl)
{
    HI_S32 ret = HI_SUCCESS;
    ret = HI_MAPI_VPROC_StopPort(vpssHdl, portHdl);
    if(ret != HI_SUCCESS) {
        printf("HI_MAPI_VPROC_StopPort error\n");
    }
    return HI_SUCCESS;

}


HI_S32 HiVideoVproc::StartDumpPort(HI_HANDLE vpssHdl, HI_HANDLE portHdl)
{
    HI_S32 ret = HI_SUCCESS;
    printf("it must call StartPort interface first\n");
    HI_MAPI_VPORT_ATTR_S dumpPortAttr;
    memset(&dumpPortAttr, 0x00, sizeof(dumpPortAttr));
    dumpPortAttr.u32Width = m_width;
    dumpPortAttr.u32Height = m_height;
    dumpPortAttr.stFrameRate.s32SrcFrameRate = 30;
    dumpPortAttr.stFrameRate.s32DstFrameRate = 30;
    dumpPortAttr.enPixelFormat = PIXEL_FORMAT_YVU_SEMIPLANAR_420;
    dumpPortAttr.enVideoFormat = VIDEO_FORMAT_LINEAR;
    dumpPortAttr.enCompressMode = COMPRESS_MODE_NONE;
    dumpPortAttr.stAspectRatio.enMode = ASPECT_RATIO_NONE;
    dumpPortAttr.lowDelayInfo.enable = HI_FALSE;

    HI_MAPI_DUMP_YUV_ATTR_S dumpYUVAttr;
    ret |= HI_MAPI_VPROC_SetPortAttr(vpssHdl, portHdl, &dumpPortAttr);
    ret |= HI_MAPI_VPROC_StartPort(vpssHdl, portHdl);
    if(ret != HI_SUCCESS) {
        printf("HI_MAPI_VPROC_StartPort error\n");
        HI_MAPI_VPROC_DeinitVpss(vpssHdl);
        return HI_FAILURE;
    }
    dumpYUVAttr.bEnable = HI_TRUE;
    dumpYUVAttr.u32Depth = 1;

    printf("HI_MAPI_VPROC_SetVpssDumpYUVAttr, vpsshdl:%d, vporthdl:%d\n", vpssHdl, portHdl);
    ret |= HI_MAPI_VPROC_SetVpssDumpYUVAttr(vpssHdl, portHdl, &dumpYUVAttr);
    if(ret != HI_SUCCESS) {
        printf("HI_MAPI_VPROC_SetVpssDumpYUVAttr error\n");
        return HI_FAILURE;
    }
    return HI_SUCCESS;

}


